﻿using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using DT.Core.Models;
using Furion;
using Furion.Authorization;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Furion.FriendlyException;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using SqlSugar;
using SqlSugar.Extensions;
using XCPFrame.Core.Enums;
using XCPFrame.Core.Plugins;

namespace XCPFrame.Application.Api
{
    /// <summary>
    /// 登录服务
    /// </summary>
    [AppAuthorize, ApiDescriptionSettings("安全管理")]
    public class LoginApiService : IDynamicApiController
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly ISqlSugarRepository repository; 
        private readonly SqlSugarClient db;

        /// <summary>
        /// LoginApiService
        /// </summary>
        /// <param name="httpContextAccessor"></param>
        /// <param name="sqlSugarRepository"></param>
        public LoginApiService(IHttpContextAccessor httpContextAccessor, ISqlSugarRepository sqlSugarRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            repository = sqlSugarRepository;
            db = repository.Context;

            if (!db.ConfigQuery.Any())
            {
                //配置用户角色
                db.ConfigQuery.SetTable<SysRole>(it => it.Id, it => it.Name);

                db.ConfigQuery.SetTable<BaUser>(it => it.Id, it => it.Name);

            }

        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        [AllowAnonymous]
        public object UserLogin(BaUser user)
        {

            BaUser _user = db.Queryable<BaUser>().Where(p=>p.Code==user.Code && p.Password==StringHelper.GeneratePassword(user.Password)).Select(it=>new BaUser
            {
                Id = it.Id.SelectAll(),
                RoleName = it.RoleId.GetConfigValue<SysRole>() 
            }).First() ?? throw Oops.Oh(SystemErrorCodes.E0001);

            // 更新最后登录时间
            var httpcontext = new IPHelper(_httpContextAccessor);
            _user.LastLoginTime = DateTime.Now.ToString();
            _user.Ip = httpcontext.GetIP() + "-" + httpcontext.GetLocation(httpcontext.GetIP()).ToString();
            _user.LastLoginEnvironment = _httpContextAccessor.HttpContext.Request.Headers["User-Agent"].FirstOrDefault().ToString();
            db.Updateable(_user).UpdateColumns(it=>new {it.LastLoginEnvironment, it.Ip, it.LastLoginTime }).ExecuteCommand();

            // 生成 token
            var jwtSettings = App.Configuration.GetSection("JWTSettings").Get<JWTSettingsOptions>();

            var datetimeOffset = DateTimeOffset.UtcNow;

            // 生成 token
            string _token = JWTEncryption.Encrypt(jwtSettings.IssuerSigningKey, new Dictionary<string, object>()
            {
                // 存储Id
                { "UserId", _user.Id },
                // 存储用户名
                { "LoginCode",_user.Code },
                // 存储角色ID
                { "RoleId", "暂空"},
                // IP地址
                { "UserIP", ""},
                // 客户端类型
                { "AppType", Guid.NewGuid().ToString()}, 
                //iat: jwt的签发时间
                { JwtRegisteredClaimNames.Iat, datetimeOffset.ToUnixTimeSeconds() },
                //nbf: 定义在什么时间之前，该jwt都是不可用的.
                { JwtRegisteredClaimNames.Nbf, datetimeOffset.ToUnixTimeSeconds() },
                //exp: jwt的过期时间，这个过期时间必须要大于签发时间
                { JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddSeconds(jwtSettings.ExpiredTime.Value * 60).ToUnixTimeSeconds() },
                //iss: jwt签发者
                { JwtRegisteredClaimNames.Iss, jwtSettings.ValidIssuer},
                //aud: 接收jwt的一方 jwtSettings.ValidAudience 接收方改变是否token通用？
                { JwtRegisteredClaimNames.Aud, jwtSettings.ValidAudience } //Guid.NewGuid().ToString()
        });

            // 设置 Swagger 刷新自动授权
            _httpContextAccessor.SigninToSwagger(_token);

            // 获取刷新 token
            var refreshToken = JWTEncryption.GenerateRefreshToken(_token, 30); // 第二个参数是刷新 token 的有效期，默认三十天

            _user.Password = "";
            _user.TokenName = _token;
            _user.RefreshTokenName = refreshToken;
            // 设置请求报文头
            _httpContextAccessor.HttpContext.Response.Headers["access-token"] = _token;
            _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

            return _user;
        }

        
    }
}
